#include "SocketPair.h"
#include "Tracer.h"
#include <fcntl.h>

SocketPair::SocketPair()
{
}
SocketPair::~SocketPair()
{
}

bool SocketPair::createPair(int& readFd, int& writeFd)
{
    int ret = socketpair(AF_UNIX,SOCK_DGRAM,0,m_fd);
    fcntl(m_fd[1],F_SETFL,O_NONBLOCK);
    if (ret<0)
    {
        TRACE_ERR_CLASS("create socket pair failed.\n");
        return false;
    }
    readFd = m_fd[PAIR_FD_READ];
    writeFd = m_fd[PAIR_FD_WRITE];
    return true;
}

bool SocketPair::bindPair(int readFd,int writeFd)
{
    m_fd[PAIR_FD_READ] = readFd;
    m_fd[PAIR_FD_WRITE] = writeFd;
    return true;
}

int SocketPair::readData(char* buf,int len,int timeoutMs)
{
    if (m_fd[PAIR_FD_READ]<0) {
        TRACE_ERR_CLASS("Invalid read fd.\n");
        return STATUS_ERROR;
    }
    struct timeval tv, *ptv;
    fd_set readfds;
    if( timeoutMs < 0)
    {
        ptv = NULL;
    }
    else
    {
        ptv = &tv;
        tv.tv_sec = timeoutMs/1000;
        tv.tv_usec = (timeoutMs%1000)*1000;
    }
    FD_ZERO(&readfds);
    FD_SET(m_fd[PAIR_FD_READ],&readfds);
    int ret = select(m_fd[PAIR_FD_READ] +1 , &readfds, NULL, NULL, ptv);
    if( 0 == ret)
    {
        TRACE_ERR_CLASS("select read timeout.\n");
        return STATUS_ERROR;
    }
    else if((ret <0) && (errno != EINTR))
    {
        TRACE_ERR_CLASS("select error: %s\n", ERROR_STRING);
        return STATUS_ERROR;
    }
    if(!FD_ISSET(m_fd[PAIR_FD_READ], &readfds))
    {
        TRACE_ERR_CLASS("readfds error\n");
        return STATUS_ERROR;
    }

    ret = read(m_fd[PAIR_FD_READ],buf,len);
    if(ret <0)
    {
        TRACE_ERR_CLASS("read msg error\n");
        return STATUS_ERROR;
    }
    return ret;
}

int SocketPair::writeData(const char* buf,int len, int timeoutMs)
{
    int ret;
    #if 0
    if (m_fd[PAIR_FD_WRITE]<0) {
        TRACE_ERR_CLASS("Invalid write fd.\n");
        return STATUS_ERROR;
    }
    struct timeval tv, *ptv;
    fd_set writefds;
    if( timeoutMs < 0)
    {
        ptv = NULL;
    }
    else
    {
        ptv = &tv;
        tv.tv_sec = timeoutMs/1000;
        tv.tv_usec = (timeoutMs%1000)*1000;
    }
    FD_ZERO(&writefds);
    FD_SET(m_fd[PAIR_FD_WRITE],&writefds);
    ret = select(m_fd[PAIR_FD_WRITE] + 1, &writefds, NULL, NULL, ptv); 
    if( 0 == ret)
    {
        TRACE_ERR_CLASS("select write timeout.\n");
        return STATUS_ERROR;
    }
    else if((ret <0) && (errno != EINTR))
    {
        TRACE_ERR_CLASS("select error: %s\n", ERROR_STRING);
        return STATUS_ERROR;
    }
    if(!FD_ISSET(m_fd[PAIR_FD_WRITE], &writefds))
    {
        TRACE_ERR_CLASS("writefds error\n");
        return STATUS_ERROR;
    }
    #endif
    /* 防止在socket关闭后,write会产生SIGPIPE信号导致进程退出 */
    //signal(SIGPIPE, SIG_IGN);
    ret = write(m_fd[PAIR_FD_WRITE], buf, len);
    if( ret<0)
    {
        TRACE_ERR_CLASS("socket pair write failed.\n");
        return STATUS_ERROR;
    }
    return ret;
}

